package demo.Editor;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.Map;

/**
 * 该类用于在Swing应用程序中创建一个临时的、可绘制的组件，主要用于在不同组件之间绘制连线
 */
public class temp extends JComponent
{
    // 存储组件对，用于在它们之间绘制连线
    private Map<JComponent, JComponent> linked;

    // 构造方法初始化linked属性
    public temp ()
    {
        super ();
        linked = new HashMap<JComponent, JComponent> ();
    }

    /**
     * 该方法用于将两个组件关联起来，并触发重绘
     * @param c1 第一个组件
     * @param c2 第二个组件
     */
    public void link ( JComponent c1, JComponent c2 )
    {
        linked.put ( c1, c2 );
        repaint ();
    }

    /**
     * 绘制组件之间的连线
     * @param g Graphics对象，用于绘制
     */
    protected void paintComponent ( Graphics g )
    {
        Graphics2D g2d = ( Graphics2D ) g;
        g2d.setRenderingHint ( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON );
        g2d.setPaint ( Color.BLACK );

        // 遍历所有关联的组件，并在它们之间绘制连线
        for ( JComponent c1 : linked.keySet () )
        {
            Point p1 = getRectCenter ( getBoundsInWindow ( c1 ) );
            Point p2 = getRectCenter ( getBoundsInWindow ( linked.get ( c1 ) ) );
            g2d.drawLine ( p1.x, p1.y, p2.x, p2.y );
        }
    }

    /**
     * 计算矩形的中心点
     * @param rect 矩形对象
     * @return 矩形的中心点
     */
    private Point getRectCenter ( Rectangle rect )
    {
        return new Point ( rect.x + rect.width / 2, rect.y + rect.height / 2 );
    }

    /**
     * 获取组件在窗口中的边界
     * @param component 组件对象
     * @return 组件在窗口中的边界
     */
    private Rectangle getBoundsInWindow ( Component component )
    {
        return getRelativeBounds ( component, getRootPaneAncestor ( component ) );
    }

    /**
     * 获取组件相对于指定组件的边界
     * @param component 组件对象
     * @param relativeTo 参考组件
     * @return 组件相对于指定组件的边界
     */
    private Rectangle getRelativeBounds ( Component component, Component relativeTo )
    {
        return new Rectangle ( getRelativeLocation ( component, relativeTo ),
                component.getSize () );
    }

    /**
     * 获取组件相对于指定组件的位置
     * @param component 组件对象
     * @param relativeTo 参考组件
     * @return 组件相对于指定组件的位置
     */
    private Point getRelativeLocation ( Component component, Component relativeTo )
    {
        Point los = component.getLocationOnScreen ();
        Point rt = relativeTo.getLocationOnScreen ();
        return new Point ( los.x - rt.x, los.y - rt.y );
    }

    /**
     * 获取组件的根窗格祖先
     * @param c 组件对象
     * @return 组件的根窗格祖先
     */
    private JRootPane getRootPaneAncestor ( Component c )
    {
        for ( Container p = c.getParent (); p != null; p = p.getParent () )
        {
            if ( p instanceof JRootPane )
            {
                return ( JRootPane ) p;
            }
        }
        return null;
    }

    /**
     * 检查指定位置是否在任何关联线的路径上
     * @param x x坐标
     * @param y y坐标
     * @return 布尔值，表示是否在关联线的路径上
     */
    public boolean contains ( int x, int y )
    {
        return false;
    }

    // 静态实例，用于在应用程序中共享
    private static temp linker;

    /**
     * 主方法，用于启动应用程序
     * @param args 命令行参数
     */
    public static void main ( String[] args )
    {
        setupLookAndFeel ();

        JFrame frame = new JFrame ();

        linker = new temp ();
        frame.setGlassPane ( linker );
        linker.setVisible ( true );

        JPanel content = new JPanel ();
        content.setLayout ( new GridLayout ( 10, 5, 5, 5 ) );
        content.setBorder ( BorderFactory.createEmptyBorder ( 5, 5, 5, 5 ) );
        frame.add ( content );

        // 创建并添加多个按钮到内容面板
        for ( int i = 0; i < 50; i++ )
        {
            final JButton button = new JButton ( "Button" + i );
            button.addActionListener ( new ActionListener ()
            {
                public void actionPerformed ( ActionEvent e )
                {
                    link ( button );
                }
            } );
            content.add ( button );
        }

        frame.setDefaultCloseOperation ( JFrame.EXIT_ON_CLOSE );
        frame.pack ();
        frame.setLocationRelativeTo ( null );
        frame.setVisible ( true );
    }

    // 记录上一个选中的按钮
    private static JButton last = null;

    /**
     * 该方法用于关联两个按钮
     * @param button 当前选中的按钮
     */
    private static void link ( JButton button )
    {
        if ( last == null )
        {
            last = button;
        }
        else
        {
            linker.link ( last, button );
            last = null;
        }
    }

    /**
     * 设置应用程序的外观风格
     */
    private static void setupLookAndFeel ()
    {
        try
        {
            UIManager.setLookAndFeel ( UIManager.getSystemLookAndFeelClassName () );
        }
        catch ( ClassNotFoundException e )
        {
            e.printStackTrace ();
        }
        catch ( InstantiationException e )
        {
            e.printStackTrace ();
        }
        catch ( IllegalAccessException e )
        {
            e.printStackTrace ();
        }
        catch ( UnsupportedLookAndFeelException e )
        {
            e.printStackTrace ();
        }
    }
}
